
package ar.com.arkios.kfconTraductor;

import ar.com.arkios.kfconmodelo.modelo.BultoPorEmbalador;
import ar.com.arkios.kfconmodelo.modelo.MessageReturnOperation;
import ar.com.arkios.kfconmodelo.modelo.Pallet;
import ar.com.arkios.kfconsap.excepciones.SapComunicationException;
import ar.com.arkios.kfconsap.excepciones.SapGeneralException;
import ar.com.arkios.kfconsap.conexion.SAPConnection;
import ar.com.arkios.kfconsap.rfc.PalletCajasInputRFC;
import java.util.List;
import org.apache.log4j.Logger;

/**
 *
 * @author Ale
 * @version 1.01
 * Clase From4DtoSAP: realiza el input a SAP, y carga el Mensaje de Retorno.
 */
public class From4DtoSAP {
    //Attributos
    private static final Logger myLogger = Logger.getLogger(From4DtoSAP.class);
    private static final int TIMEOUT = 240000;//60*4=240 o sea 4 minutos
    private static final int TIMESLEEP = 50;
    
    MessageReturnOperation myMessageReturnOperation;
    PalletCajasInputRFC aPalletCajasInputRFC;
    List<Pallet> misPallets;
    List<BultoPorEmbalador> misBultosPorEmbalador;
    //Constructores
    public From4DtoSAP(List<Pallet> pallets, List<BultoPorEmbalador> bultosPorEmbalador) throws Exception {
        this.misPallets = pallets;
        this.misBultosPorEmbalador = bultosPorEmbalador;
        try {
            executeRFC_UP();
        } catch (SapGeneralException e) {
            String mensaje = e.getMessage();
            try{
                SAPConnection.getInstance().close();
                myLogger.error("Se Cierra la Conexion con SAP al tratar de Ejecutarse la RFC_UP Detalle: " + e.getMessage());
            } catch (SapComunicationException ex) {
                myLogger.error("Error al tratar de cerrar la conexión sap: " + ex.getMessage());
                mensaje += " - " + ex.getMessage();
            } finally {
                throw new Exception(mensaje);
            }            
        }
    }

    public MessageReturnOperation getMyMessageReturnOperation() {
        return myMessageReturnOperation;
    }
    
    private void executeRFC_UP() {
        SAPEjecutor executer = new SAPEjecutor(this);
        long tiempoExecuter = 0;
        final long tiempoInicio = System.currentTimeMillis();
        //int contadorVueltas = 0;// Creado para analizar posibles cuelgues.
                
        executer.start();
        myLogger.debug("executeRFC_UP: se ejecuto executer.start()");
        boolean entroAlMenosUnaVez = false;
        while ((tiempoExecuter < TIMEOUT) && (executer.isAlive())) {
            entroAlMenosUnaVez = true;
            tiempoExecuter = (System.currentTimeMillis() - tiempoInicio);
            //contadorVueltas++;
            try {
                //myLogger.debug("executeRFC_UP: Vuelta Nro: "+ contadorVueltas);
                //myLogger.debug("executeRFC_UP: El Thread se va a dormir: "+TIMESLEEP + " Milisegundos.");
                Thread.sleep(TIMESLEEP);
            } catch (Exception e) {
                myLogger.error("executeRFC_UP: No se pudo realizar la espera de ejecución de la subida de datos.");
                myLogger.error(e);
                throw new SapGeneralException("No se pudo realizar la espera de ejecución de la subida de datos.");
            }
        }
        
        if (executer.isAlive()) {
            myLogger.error("executeRFC_UP: La operación de subida tomó demasiado tiempo.");
            myLogger.error("info: Thread-ID: " + executer.getId() + " - Thread-State: " + executer.getState() + "EntroUnaVez: " + entroAlMenosUnaVez);
            throw new SapGeneralException("executeRFC_UP: La operación de subida tomó demasiado tiempo.");

        }else{
            myLogger.debug("executeRFC_UP: El executer ya no esta vivo.");
        }
        
        String elStatus = "";
        try {
            elStatus = SAPConnection.getInstance().getMyStatus();
        } catch (SapComunicationException e) {
            myLogger.error("Error durante setMyStatus");
        }
        if (elStatus.isEmpty())
            myLogger.debug("executeRFC_UP: Se ejecutó correctamente sin timeout la subida de datos");
        else {
            myLogger.debug("executeRFC_UP: Se ejecutó con ERROR pero sin timeout la subida de datos");
            throw new SapGeneralException("Error en subida datos: " + elStatus);
        }
    }
   
    private class SAPEjecutor extends Thread {
        
        private final Logger myLogger = Logger.getLogger(SAPEjecutor.class);
        
        private From4DtoSAP f4dtsap;
        
        public SAPEjecutor(From4DtoSAP elF4dtsap) {
            this.f4dtsap = elF4dtsap;
        }

        @Override
        public void run() {
            try{
                myLogger.debug("SAPEjecutor: Inicia el metodo run()");
                f4dtsap.aPalletCajasInputRFC = new PalletCajasInputRFC();
                f4dtsap.aPalletCajasInputRFC.saveAll(f4dtsap.misPallets, f4dtsap.misBultosPorEmbalador);
                f4dtsap.aPalletCajasInputRFC.executeFunction();
                myLogger.debug("SAPEjecutor: ejecuto la RFC de Subida.");
                f4dtsap.aPalletCajasInputRFC.clearData();
                f4dtsap.aPalletCajasInputRFC.executeReturn();
                myLogger.debug("SAPEjecutor: ejecuto el RETURN con exito.");
                f4dtsap.myMessageReturnOperation = aPalletCajasInputRFC.getMyReturnDAO().getAMessageReturnOperation();
                
                SAPConnection.getInstance().close();
                myLogger.debug("SAPEjecutor: Cerro la Conexion con SAP.");
            } catch(SapGeneralException ex) {
                try {
                    myLogger.error("SAPEjecutor: Ocurrió un error SapGeneralException al ejecutar la subida de datos" + ex.getMessage());
                    SAPConnection.getInstance().setMyStatus(ex.getMessage());
                } catch (SapComunicationException ex1) {
                     myLogger.error("Error durante setMyStatus");
                }
            } catch(SapComunicationException ex) {
                try {
                    myLogger.error("SAPEjecutor: Ocurrió un error SapComunicationException al ejecutar la subida de datos: " + ex.getMessage());
                    SAPConnection.getInstance().setMyStatus(ex.getMessage());
                } catch (SapComunicationException ex1) {
                    myLogger.error("Error durante setMyStatus");
                }
            } catch (Throwable t) {// para que no se nos escape nada de nada
                try {                   
                    myLogger.error("SAPEjecutor: Ocurrió un error Throwable al ejecutar la subida de datos: " + t.getMessage());
                    SAPConnection.getInstance().setMyStatus(t.getMessage());
                } catch (SapComunicationException ex) {
                    myLogger.error("Error durante setMyStatus");
                }
            }
        }
    }   
   
}
